package com.gopay.common.util.xml.utils;

import com.gopay.common.util.LogUtil;
import com.gopay.common.util.xml.utils.converters.BigDecimalConverter;
import com.gopay.common.util.xml.utils.converters.DefaultConverter;
import com.gopay.common.util.xml.utils.converters.DefaultStringConverter;
import com.gopay.common.util.xml.utils.converters.IntegerConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.math.BigDecimal;

public class BeanConverterUtil {
	/** logger */
	private static final Logger LOGGER = LoggerFactory.getLogger(BeanConverterUtil.class);

	private static BeanConverterUtil instance;

	private final static WeakFastHashMap converters = new WeakFastHashMap();

	private BeanConverterUtil() {
		converters.setFast(false);
		deregister();
		converters.setFast(true);
	}

	public static BeanConverterUtil getInstance() {
		if (instance == null) {
			synchronized(BeanConverterUtil.class){
				instance = new BeanConverterUtil();
			}
		}
		return instance;
	}

	public Converter getConverter(String type) {
		boolean b = converters.containsKey(type);
		return b ? (Converter)converters.get(type) : (Converter)converters.get("otherConverter");
	}

	public void register(String type, Converter converter) {
		converters.put(type, converter);
	}

	private void deregister() {
		converters.clear();
		converters.put(BigDecimal.class.getName(), new BigDecimalConverter(null));
		converters.put(Integer.class.getName(), new IntegerConverter(null));
		converters.put(String.class.getName(), new DefaultStringConverter(null));
		converters.put("otherConverter", new DefaultConverter(null));
	}

	/**
	 * 对象互转
	 * @author <a href="mailto:yhwpeng@126.com">wangdong</a>
	 * @date 2017-08-09 13:09:10
	 */
	public static Object convertBean2Bean(Object from, Object to) {
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(to.getClass());
			PropertyDescriptor[] ps = beanInfo.getPropertyDescriptors();

			for (PropertyDescriptor p : ps) {
				Method getMethod = p.getReadMethod();
				Method setMethod = p.getWriteMethod();
				if (getMethod != null && setMethod != null) {
					try {
						Object result = getMethod.invoke(from);
						setMethod.invoke(to, result);
					} catch (Exception e) {
						// 如果from没有此属性的get方法，跳过
						continue;
					}
				}
			}
		} catch (Exception e) {
			LogUtil.error(LOGGER, e, "转换出错");
		}
		return to;
	}
}
